# coding = <utf-8>

# 导入tkinter模块
import re
import tkinter as tk
from tkinter import ttk
import serial.tools.list_ports
import myserial


class ModbusMasterGui():
    def __init__(self,serial = None):
        # 创建主窗口
        self.root = tk.Tk()
        # 设置窗口标题
        self.root.title("Modbus Master")
        # 设置窗口大小(全屏)+打开位置
        self.root.geometry("980x780")
        # 设置窗口是否可变
        self.root.resizable(width=True, height=True)
        # 图标样式
        self.root.iconbitmap("logo.ico")
        # 创建串口对象
        self.serial = serial
        # 创建串口参数
        self.CreateWidgets()
        # 主循环开启窗口，其他语句需要在该代码上才可生效
        # self.root.mainloop()

    def mainloop(self):
        self.root.mainloop()

    def CreateWidgets(self):
        # 主框架
        FrameMain = tk.Frame(self.root)
        FrameMain.pack(fill=tk.BOTH, expand=True)

        # 连接管理
        connection_frame = tk.LabelFrame(FrameMain, text="连接管理")
        connection_frame.pack(fill=tk.X, expand=False, padx=10, pady=5)

        # 连接按钮
        self.button_connect = tk.Button(connection_frame, text="建立连接", bg="red", command=self.Connect)
        self.button_connect.grid(row=0, column=0, padx=5, pady=5)

        # 串口选择
        # ports = [port.device for port in serial.tools.list_ports.comports()]
        # ports = [port.description for port in serial.tools.list_ports.comports()]
        ports = self.serial.get_serial_ports()
        if not ports:
            ports = ["无可用串口"]
        tk.Label(connection_frame, text="串口号").grid(row=0, column=1, padx=5, pady=2)
        self.combobox_port = ttk.Combobox(connection_frame, width=25, values=ports)
        self.combobox_port.grid(row=0, column=2, padx=5, pady=5)
        self.combobox_port.current(0)
        self.combobox_port.bind('<Button-1>', self.combobox_port_click)  # 绑定点击事件
        # 波特率选择
        tk.Label(connection_frame, text="波特率").grid(row=0, column=3, padx=5, pady=5)
        self.combobox_baudrate = ttk.Combobox(connection_frame, width=10, values=["9600", "19200", "38400", "57600", "115200"])
        self.combobox_baudrate.grid(row=0, column=4, padx=5, pady=5)
        self.combobox_baudrate.current(0)
        # 数据位选择
        tk.Label(connection_frame, text="数据位").grid(row=0, column=5, padx=5, pady=5)
        self.combobox_bytesize = ttk.Combobox(connection_frame, width=10, values=["5", "6", "7", "8"])
        self.combobox_bytesize.grid(row=0, column=6, padx=5, pady=5)
        self.combobox_bytesize.current(3)
        # 停止位选择
        tk.Label(connection_frame, text="停止位").grid(row=0, column=7, padx=5, pady=5)
        self.combobox_stopbits = ttk.Combobox(connection_frame, width=10, values=["1", "1.5", "2"])
        self.combobox_stopbits.grid(row=0, column=8, padx=5, pady=5)
        self.combobox_stopbits.current(0)
        # 校验位选择
        tk.Label(connection_frame, text="校验位").grid(row=0, column=9, padx=5, pady=5)
        self.combobox_parity = ttk.Combobox(connection_frame, width=10, values=["N", "E", "O", "M", "S"])
        self.combobox_parity.grid(row=0, column=10, padx=5, pady=5)
        self.combobox_parity.current(0)

        # 读写任务
        self.register_frame = tk.LabelFrame(FrameMain, text="读写任务")
        self.register_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        # 绑定右键事件
        self.register_frame.bind("<Button-3>", self.ShowContextMenu)

        # 通讯交互
        console_frame = tk.LabelFrame(FrameMain, height=150, text="通讯交互")
        console_frame.pack(fill=tk.X, expand=False, padx=10, pady=5)

    def combobox_port_click(self, event):
        # 串口选择框点击事件
        ports = self.serial.get_serial_ports()
        if not ports:
            ports = ["无可用串口"]
        self.combobox_port.config(values=ports)

    def Connect(self):
        # 获取串口参数
        port = self.combobox_port.get()
        baudrate = int(self.combobox_baudrate.get())
        bytesize = int(self.combobox_bytesize.get())
        stopbits = float(self.combobox_stopbits.get())
        parity = self.combobox_parity.get()

        if not port:
            print("port is null")
            return
        try:
            if not self.serial.get_serial_status():
                if not self.serial.open_serial_port(port, baudrate, bytesize, parity, stopbits):
                    return
            self.button_connect.config(text="断开连接", bg="green")
            self.button_connect.config(command=self.Disconnect)
        except Exception as e:
            print(e)

    def Disconnect(self):
        # 断开连接
        if self.serial.get_serial_status():
            self.serial.close_serial_port()
        self.button_connect.config(text="建立连接", bg="red")
        self.button_connect.config(command=self.Connect)

    def ShowContextMenu(self, event):
        # 创建右键菜单
        self.context_menu = tk.Menu(self.root, tearoff=False)
        self.context_menu.add_command(label="增加写任务", command=self.AddWriteTask)
        self.context_menu.add_command(label="增加读任务", command=self.AddReadTask)
        self.context_menu.add_command(label="清空任务", command=self.DeleteTask)
        # 显示菜单
        self.TmpWindowX = event.x_root
        self.TmpWindowY = event.y_root
        self.context_menu.post(event.x_root, event.y_root)

    def AddWriteTask(self):
        # 这里弹出一个窗口
        self.tmp_write_frame = tk.Toplevel(self.register_frame)
        self.tmp_write_frame.geometry("180x200+{}+{}".format(self.TmpWindowX,self.TmpWindowY))
        self.tmp_write_frame.title("写任务添加")
        self.tmp_write_frame.resizable(width=False, height=False)
        self.tmp_write_frame.transient(self.register_frame)
        self.tmp_write_frame.grab_set()

        # 寄存器地址输入框
        tk.Label(self.tmp_write_frame, text="从机地址").grid(row=0, column=0, padx=5, pady=5)
        self.entry_write_address = tk.Entry(self.tmp_write_frame, width=10)
        self.entry_write_address.grid(row=0, column=1, padx=5, pady=5)
        self.entry_write_address.insert(0, "1")

        # 寄存器值输入框
        tk.Label(self.tmp_write_frame, text="起始地址").grid(row=1, column=0, padx=5, pady=5)
        self.entry_write_value = tk.Entry(self.tmp_write_frame, width=10)
        self.entry_write_value.grid(row=1, column=1, padx=5, pady=5)

        # 寄存器类型选择
        tk.Label(self.tmp_write_frame, text="地址数量").grid(row=2, column=0, padx=5, pady=5)
        self.combobox_write_type = tk.Entry(self.tmp_write_frame, width=10)
        self.combobox_write_type.grid(row=2, column=1, padx=5, pady=5)

        # 查询周期
        tk.Label(self.tmp_write_frame, text="指令周期ms").grid(row=3, column=0, padx=5, pady=5)
        self.entry_write_count = tk.Entry(self.tmp_write_frame, width=10)
        self.entry_write_count.grid(row=3, column=1, padx=5, pady=5)
        self.entry_write_count.insert(0, "1000")

        # 确认按钮
        self.button_write_confirm = tk.Button(self.tmp_write_frame, text="新增", command=self.ConfirmWriteTask)
        self.button_write_confirm.grid(row=4, column=0, columnspan=2, padx=5, pady=5)

        # 增加提示信息
        tk.Label(self.tmp_write_frame, text="提示：请输入十进制数").grid(row=5, column=0, columnspan=2, padx=5, pady=5)

    def AddReadTask(self):
        # 这里弹出一个窗口
        self.tmp_read_frame = tk.Toplevel(self.register_frame)
        self.tmp_read_frame.geometry("180x200+{}+{}".format(self.TmpWindowX,self.TmpWindowY))
        self.tmp_read_frame.title("读任务添加")
        self.tmp_read_frame.resizable(width=False, height=False)
        self.tmp_read_frame.transient(self.register_frame)
        self.tmp_read_frame.grab_set()

        # 寄存器地址输入框
        tk.Label(self.tmp_read_frame, text="从机地址").grid(row=0, column=0, padx=5, pady=5)
        self.entry_read_address = tk.Entry(self.tmp_read_frame,width=10)
        self.entry_read_address.grid(row=0, column=1, padx=5, pady=5)
        self.entry_read_address.insert(0, "1")

        # 寄存器值输入框
        tk.Label(self.tmp_read_frame, text="起始地址").grid(row=1, column=0, padx=5, pady=5)
        self.entry_read_value = tk.Entry(self.tmp_read_frame, width=10)
        self.entry_read_value.grid(row=1, column=1, padx=5, pady=5)

        # 寄存器类型选择
        tk.Label(self.tmp_read_frame, text="地址数量").grid(row=2, column=0, padx=5, pady=5)
        self.combobox_read_type = tk.Entry(self.tmp_read_frame, width=10)
        self.combobox_read_type.grid(row=2, column=1, padx=5, pady=5)

        # 查询周期
        tk.Label(self.tmp_read_frame, text="指令周期ms").grid(row=3, column=0, padx=5, pady=5)
        self.entry_read_count = tk.Entry(self.tmp_read_frame, width=10)
        self.entry_read_count.grid(row=3, column=1, padx=5, pady=5)
        self.entry_read_count.insert(0, "1000")

        # 确认按钮
        self.button_read_confirm = tk.Button(self.tmp_read_frame, text="新增", command=self.ConfirmReadTask)
        self.button_read_confirm.grid(row=4, column=0, columnspan=2, padx=5, pady=5) 

        # 增加提示信息
        tk.Label(self.tmp_read_frame, text="提示：请输入十进制数").grid(row=5, column=0, columnspan=2, padx=5, pady=5)       

    def DeleteTask(self):
        # 这里弹出一个窗口
        self.tmp_delete_frame = tk.Toplevel(self.register_frame)
        self.tmp_delete_frame.geometry("150x80+{}+{}".format(self.TmpWindowX,self.TmpWindowY))
        self.tmp_delete_frame.title("清空任务")
        self.tmp_delete_frame.resizable(width=False, height=False)
        self.tmp_delete_frame.transient(self.register_frame)
        self.tmp_delete_frame.grab_set()

        # 确认按钮
        self.button_delete_confirm = tk.Button(self.tmp_delete_frame, text="确认", command=self.ConfirmDeleteTask)
        self.button_delete_confirm.grid(row=0, columnspan=2, padx=5, pady=5)

        # 增加提示信息
        tk.Label(self.tmp_delete_frame, text="提示：所有任务将被清空").grid(row=1, columnspan=2, padx=5, pady=5)


    def ConfirmWriteTask(self):
        # 获取输入框内容

        # 关闭窗口
        self.tmp_write_frame.destroy()

    def ConfirmReadTask(self):
        # 获取输入框内容

        # 关闭窗口
        self.tmp_read_frame.destroy()

    def ConfirmDeleteTask(self):
        
        # 关闭窗口
        self.tmp_delete_frame.destroy()

    def AddRWTask(self):
        # 产生一个新Frame，鼠标右键点击该Frame时显示右键菜单：启动任务、停止任务、删除任务
        # 显示任务当前状态：运行中、停止中
        # 显示一个列表，列表行项：寄存器地址、寄存器值
        pass


# # 运行应用
# if __name__ == "__main__":
#     # 创建主窗口
#     root = tk.Tk()
#     # 获取当前根窗口最大分辨率
#     RootX,RootY = root.maxsize()
#     # 设置窗口标题
#     root.title("Modbus Master")
#     # 设置窗口大小(全屏)+打开位置
#     root.geometry("880x600")
#     # 设置窗口是否可变
#     root.resizable(width=True, height=True)
#     # 图标样式
#     root.iconbitmap("logo.ico")
#     # 创建ModbusMasterGui类实例
#     app = ModbusMasterGui(root)
#     # 主循环开启窗口，其他语句需要在该代码上才可生效
#     root.mainloop()
